package com.maiji.cloud.utils;

import java.io.File;
import java.io.FileInputStream;
import java.io.InputStream;
import java.lang.reflect.Field;
import java.security.KeyStore;
import java.security.SecureRandom;
import java.util.*;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.github.wxpay.sdk.WXPayConstants;
import com.github.wxpay.sdk.WXPayUtil;
import com.google.common.collect.Maps;
import org.apache.commons.lang.StringUtils;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.conn.ssl.DefaultHostnameVerifier;
import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.impl.conn.BasicHttpClientConnectionManager;
import org.apache.http.util.EntityUtils;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.web.client.RestTemplate;

import javax.net.ssl.KeyManagerFactory;
import javax.net.ssl.SSLContext;


import javax.crypto.Cipher;
import javax.crypto.NoSuchPaddingException;
import javax.crypto.spec.SecretKeySpec;
import java.security.InvalidKeyException;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.security.Security;


public class WXUtil {

    public static final String APP_ID = "wxa078f88515c25ee8";
    
    public static final String APPLET_APP_ID = "wxda96e55a954ddae4";
    //微信商户号
    public static final String MCH_ID = "1483499032";
    //微信支付密钥
    public static final String KEY = "Maijijianfeifashangcheng111111aa";
    //微信支付成功回调url
    public static final String NOTIFY_URL = "https://api.imaiji.cn/capitalInteface/weixinPayCallBack";
    
    //微信退款成功回调
    public static final String REFUND_NOTIFY_URL = "https://api.imaiji.cn/capitalInteface/refundCallBack";

    public static final String SIGN_PACKAGE = "Sign=WXPay";

    private static Cipher cipher = null;  //解码器
    
    public static String createSign(Map parameters) throws Exception {

        List<String> keys = new ArrayList<String>(parameters.keySet());
        Collections.sort(keys);
        String prestr = "";
        for (int i = 0; i < keys.size(); i++) {
        String key = keys.get(i);
        Object value = parameters.get(key);
//        value = URLEncoder.encode(value, "UTF-8");
        if(StringUtils.isNotBlank(parameters.get(key)+"") && value != null) {
        	if (i == keys.size() - 1) {//拼接时，不包括最后一个&字符
                prestr = prestr + key + "=" + value;
            } else {
                prestr = prestr + key + "=" + value + "&";
            }	
        }
        
       
        }
        prestr += "&key="+KEY;
        return prestr;
    }
    
    public static Map<String, Object> objectToMap(Object obj) throws Exception { 
    	if(obj == null){ 
    	return null; 
    	} 

    	Map<String, Object> map = new HashMap<String, Object>(); 

    	Field[] declaredFields = obj.getClass().getDeclaredFields(); 
    	for (Field field : declaredFields) { 
    	field.setAccessible(true); 
    	map.put(field.getName(), field.get(obj)); 
    	} 

    	return map; 
    	}

    public static Map applayRefund(String userId, String payId, String orderNo, Double amount, Double refundMoney) throws Exception {
        Map map = new HashMap();
        map.put("appid", APP_ID);
        map.put("mch_id", MCH_ID);
        map.put("nonce_str", UUID_MD5.getUUID());
        map.put("transaction_id", payId);
        map.put("out_refund_no", orderNo);
        int total_fee = (int) (amount * 100);
        map.put("total_fee", total_fee+"");
        int refund_fee = (int) (refundMoney * 100);
        map.put("refund_fee", refund_fee+"");
        map.put("notify_url", REFUND_NOTIFY_URL);
                             
        String stringSign = WXUtil.createSign(map);
        String sign = WXPayUtil.MD5(stringSign).toUpperCase();
        map.put("sign", sign);

        String data = WXPayUtil.mapToXml(map);

        File file = new File("apiclient_cert.p12");
        InputStream in = new FileInputStream(file);

        char password[] = WXUtil.MCH_ID.toCharArray();
        java.io.InputStream certStream = in;
        KeyStore ks = KeyStore.getInstance("PKCS12");
        ks.load(certStream, password);
        KeyManagerFactory kmf = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
        kmf.init(ks, password);
        SSLContext sslContext = SSLContext.getInstance("TLS");
        sslContext.init(kmf.getKeyManagers(), null, new SecureRandom());
        SSLConnectionSocketFactory sslConnectionSocketFactory = new SSLConnectionSocketFactory(sslContext,
                new String[] { "TLSv1" }, null, new DefaultHostnameVerifier());

        BasicHttpClientConnectionManager connManager = new BasicHttpClientConnectionManager();
        CloseableHttpClient httpClient = HttpClients.custom().setSSLSocketFactory(sslConnectionSocketFactory).build();
        String url = (new StringBuilder()).append("https://").append("api.mch.weixin.qq.com")
                .append("/secapi/pay/refund").toString();
        HttpPost httpPost = new HttpPost(url);
        RequestConfig requestConfig = RequestConfig.custom().setSocketTimeout(10000).setConnectTimeout(10000).build();
        httpPost.setConfig(requestConfig);
        StringEntity postEntity = new StringEntity(data, "UTF-8");
        httpPost.addHeader("Content-Type", "text/xml");
        httpPost.addHeader("User-Agent", (new StringBuilder()).append(WXPayConstants.USER_AGENT).append(" ")
                .append(map.get("mch_id")).toString());
        httpPost.setEntity(postEntity);
        CloseableHttpResponse httpResponse = httpClient.execute(httpPost);
        org.apache.http.HttpEntity httpEntity = httpResponse.getEntity();
        String reponseString = EntityUtils.toString(httpEntity, "UTF-8");
        return WXPayUtil.xmlToMap(reponseString);
    }
    
    /**
     * 提现
     * @param openid 微信openid
     * @param realName 真实姓名
     * @param money 提现金额
     * @return
     * @throws Exception
     */
    public static Map wxWithdraw(String openid,String realName, Double money) throws Exception{
    	  Map map = new HashMap();
          map.put("mch_appid", APP_ID);
          map.put("mchid", MCH_ID);
          map.put("nonce_str", UUID_MD5.getUUID());
          map.put("partner_trade_no", UUID_MD5.getUUID());
          map.put("openid", openid);
          map.put("check_name", "FORCE_CHECK");
          map.put("re_user_name", realName);
          int total_fee = (int) (money * 100);
          map.put("amount", total_fee+"");
          map.put("desc", "账户提现");
          map.put("spbill_create_ip", "47.105.145.211");
          String stringSign = WXUtil.createSign(map);
          String sign = WXPayUtil.MD5(stringSign).toUpperCase();
          map.put("sign", sign);

          String data = WXPayUtil.mapToXml(map);

          File file = new File("apiclient_cert.p12");
          InputStream in = new FileInputStream(file);

          char password[] = WXUtil.MCH_ID.toCharArray();
          java.io.InputStream certStream = in;
          KeyStore ks = KeyStore.getInstance("PKCS12");
          ks.load(certStream, password);
          KeyManagerFactory kmf = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
          kmf.init(ks, password);
          SSLContext sslContext = SSLContext.getInstance("TLS");
          sslContext.init(kmf.getKeyManagers(), null, new SecureRandom());
          SSLConnectionSocketFactory sslConnectionSocketFactory = new SSLConnectionSocketFactory(sslContext,
                  new String[] { "TLSv1" }, null, new DefaultHostnameVerifier());

          BasicHttpClientConnectionManager connManager = new BasicHttpClientConnectionManager();
          CloseableHttpClient httpClient = HttpClients.custom().setSSLSocketFactory(sslConnectionSocketFactory).build();
          String url = (new StringBuilder()).append("https://").append("api.mch.weixin.qq.com")
                  .append("/mmpaymkttransfers/promotion/transfers").toString();
          HttpPost httpPost = new HttpPost(url);
          RequestConfig requestConfig = RequestConfig.custom().setSocketTimeout(10000).setConnectTimeout(10000).build();
          httpPost.setConfig(requestConfig);
          StringEntity postEntity = new StringEntity(data, "UTF-8");
          httpPost.addHeader("Content-Type", "text/xml");
          httpPost.addHeader("User-Agent", (new StringBuilder()).append(WXPayConstants.USER_AGENT).append(" ")
                  .append(map.get("mch_id")).toString());
          httpPost.setEntity(postEntity);
          CloseableHttpResponse httpResponse = httpClient.execute(httpPost);
          org.apache.http.HttpEntity httpEntity = httpResponse.getEntity();
          String reponseString = EntityUtils.toString(httpEntity, "UTF-8");
          return WXPayUtil.xmlToMap(reponseString);
    	
    	
    }
    
    /**
  * 微信返回参数解密
  * @param reqInfo
  * @return
  * @throws Exception
  */
    public static Map parseReqInfo(String reqInfo) throws Exception {
    	init();
        Base64.Decoder decoder = Base64.getDecoder();
        byte[] base64ByteArr = decoder.decode(reqInfo);
 
        String result = new String(cipher.doFinal(base64ByteArr));
        return WXPayUtil.xmlToMap(result);
    }
 
    public static void init() {
        String key = getMD5(KEY);
        SecretKeySpec secretKeySpec = new SecretKeySpec(key.getBytes(), "AES");
        Security.addProvider(new BouncyCastleProvider());
        try {
            cipher = Cipher.getInstance("AES/ECB/PKCS7Padding");
            cipher.init(Cipher.DECRYPT_MODE, secretKeySpec);
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
        } catch (NoSuchPaddingException e) {
            e.printStackTrace();
        } catch (InvalidKeyException e) {
            e.printStackTrace();
        }
    }
 
    public static String getMD5(String str) {
        try {
            MessageDigest md = MessageDigest.getInstance("MD5");
            String result = MD5(str, md);
            return result;
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
            return "";
        }
    }
 
    public static String MD5(String strSrc, MessageDigest md) {
        byte[] bt = strSrc.getBytes();
        md.update(bt);
        String strDes = bytes2Hex(md.digest());
        return strDes;
    }
 
    public static String bytes2Hex(byte[] bts) {
        StringBuffer des = new StringBuffer();
        String tmp = null;
        for (int i = 0; i < bts.length; i++) {
            tmp = (Integer.toHexString(bts[i] & 0xFF));
            if (tmp.length() == 1) {
                des.append("0");
            }
            des.append(tmp);
        }
        return des.toString();}

    public static Boolean examineText (String text) {
        if (StringUtils.isBlank(text)) return true;
        JSONObject jsonObject = JSON.parseObject(new RestTemplate().getForObject("https://api.weixin.qq.com/cgi-bin/token?" +
                "appid=wxda96e55a954ddae4&secret=bcbc8087160a4b7fdc05cdfb0e7c85dd&grant_type=client_credential", String.class));
        String access_token = (String) jsonObject.get("access_token");
        HashMap<Object, Object> map = Maps.newHashMap();
        map.put("content", text);
        HttpHeaders headers = new HttpHeaders();
        headers.setContentType(MediaType.APPLICATION_JSON);
        HttpEntity requestEntity = new HttpEntity(map, headers);
        JSONObject jsonObject1 = JSON.parseObject(new RestTemplate().postForObject(
                "https://api.weixin.qq.com/wxa/msg_sec_check?access_token=" + access_token, requestEntity, String.class));
        Integer errcode = (Integer) jsonObject1.get("errcode");
        return errcode == 0;
    }


    public static void main(String[] args) {
        System.out.println(examineText("求助从第三天开始我就进入平台期了，一直没怎么瘦，也没有破戒，今早测的尿酮试纸这个颜色，代表应该有脂肪燃烧啊，可是为什么我就是不瘦啊，要疯了，现在都低血糖了，天天头晕乏力心慌，再这样下去真的坚持不了了"));

        /*Map map = new HashMap();
        map.put("appid", APP_ID);
        map.put("mch_id", MCH_ID);
        map.put("nonce_str", UUID_MD5.getUUID());
        map.put("sign_type", "MD5");
        map.put("body", "麦吉-商品支付");
        map.put("fee_type", "CNY");
        map.put("total_fee", 3+"");
        map.put("spbill_create_ip", "192.168.100.8");
        map.put("notify_url", NOTIFY_URL);
        map.put("trade_type", "APP");
        try {
            System.out.println(WXUtil.applayRefund("58d6c8f4ff564963a4aaa092a5416246","4200000471201911155957141995","18507835799906419507",5.91,5.91));
        } catch (Exception e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }*/
    }
    
}
